Skip to content

workflow: Hand a task names each lane's Project in its pick list - #2242

Merged
Birfy merged 1 commit into
ThinkFlowLab:mainfrom
HugoXK:dev/1-p450-assign-dialog-project
Nov 3, 2026
Merged

Birfy merged 1 commit into
ThinkFlowLab:mainfrom
HugoXK:dev/1-p450-assign-dialog-project

Conversation

@HugoXK

@HugoXK HugoXK commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #2241

Owner: Dev
Written-by: Dev-1
Reviewer: Birfy
Claim-Id: 0b70a4567eb74831a7cb661cebd26ae2
Branch: dev/1-p450-assign-dialog-project
Base: 7d1f1bb
Tier: T2 (gate reading at this tip: computedTier = T2, exemptFromPass = false; plugins/** matches, and the highest matching path tier wins)
Tree: 35f280d730782100cfa77720c836488f47abb342
Verified tree: 35f280d730782100cfa77720c836488f47abb342 — npm run verify ran on this tree in local commit 4c2f74b811194c7fac9558a7cfb0243bc0b60dfd, which was never pushed and which GitHub cannot resolve
Pushed head: 65914e2 (same tree 35f280d730782100cfa77720c836488f47abb342, generated from it by the push path)
Files: 4 changed, +88/−4
Single parent: 7d1f1bb

What changes

The Hand a task to a Workflow dialog drew each lane's name and chain, never its Project, so two
lanes from different Projects read exactly alike at the moment a card is handed over. The list row
already repeats that badge from the same projects listing (client.js:2232), so AssignModal
now takes projects, resolves the name once through projectName(id), and draws the same
wf-proj span after the Workflow badge on every target row (wf-t1).

A lane with no projectId draws no badge at all, not an Unassigned placeholder (owner decision in
#2241): the dialog is a choice, not the list, so the absent badge already says "no Project" and a
placeholder would add one more sentence to translate for no information. The list row's own
Unassigned branch stays exactly as it was.

Nothing else moves. The assign call gains no projectId argument, confirmAssign's submit body is
byte-identical (the third test pins it), the card row is untouched, and AssignModal's existing
error slot keeps the shape #2237 gave it.

Docs: the Project paragraph of docs/subsystems/workflow.md now names the dialog. Changelog:
changelog.d/2241-hand-a-task-project-badge.added.md.

Red first

Run on the live base 7d1f1bb7 with the test file from this branch and the source at that base
(git show 7d1f1bb7:plugins/workflow/client.js > plugins/workflow/client.js):

$ TZ=UTC node --test plugins/workflow/test/client.test.js
not ok 148 - #2241: the Hand a task dialog names each lane's Project
  the first lane names its Project, saw Lane AWorkflowPlanner → Writer → Coder → Reviewer ‖ Tester → Deployer
not ok 149 - #2241: a lane with no Project carries no Project badge
  only the two lanes that have a Project draw the badge
  0 !== 2
ok 150 - #2241: picking a lane still posts the same assign body
# tests 150
# pass 148
# fail 2

Read against the issue's own two counter-cases: not ok 149 shows the base draws zero Project
badges in the dialog, and ok 150 is already green there — this change must leave the submit body
alone, and the third test keeps it that way.

With the fix in place the same file runs # tests 150 / # pass 150 / # fail 0.

Files

4 files, +88/−4: plugins/workflow/client.js (+8/−3 — one prop, one resolver, one badge),
plugins/workflow/test/client.test.js (+78), docs/subsystems/workflow.md (+1/−1),
changelog.d/2241-hand-a-task-project-badge.added.md (+1).

Ran

  • Red first above on 7d1f1bb7, then TZ=UTC node --test plugins/workflow/test/client.test.js →
    150/150/0 on the fixed tip, and npm --prefix plugins/workflow test → 392/392/0.
  • TZ=UTC ARCH_DOCS_BASE=7d1f1bb7ed2f097beb5376eb48f08cfeed794c3b npm run verify → exit 0,
    4569/4569/0: core 2674, social 570, tree 131, timeline 140, workflow 392, .github/scripts
    599, interop 37, live-e2e 26.
  • In that chain: arch-docs: OK (4 changed file(s)); ok core/ equals ds-bot/ + patches/ds-bot/;
    ok 10 patches apply cleanly in order; ok patches/ds-bot/ is what generate writes (generate is a no-op); build-client.mjs --check green; all four packed plugins imported; the changelog.d/
    check green.

Not run

  • The smoke test: core/index.js and core/src/host/ are untouched.
  • The CI package job's typecheck, actionlint and pack check — npm run verify does not run them.
  • npm_config_cache pointed at a workspace directory for this run: ~/.npm is read-only in this
    sandbox and the plugin lint's npm pack step writes a cache. Nothing else in the suite depends
    on it.

Checkpoint

{
"pr": 2242,
"claim": "Dev",
"issue": 2241,
"summary": "The Hand a task to a Workflow dialog now names each lane's Project on its target row, reusing the wf-proj badge and projects listing the list row already draws, so two lanes from different Projects no longer read alike at the pick point. A lane with no Project draws no badge, by owner decision, instead of an Unassigned placeholder. The assign call gains no projectId argument and confirmAssign's submit body is unchanged. Docs and a changelog fragment name the dialog.",
"files": [
"plugins/workflow/client.js",
"plugins/workflow/test/client.test.js",
"docs/subsystems/workflow.md",
"changelog.d/2241-hand-a-task-project-badge.added.md"
],
"checks": {
"ran": "TZ=UTC ARCH_DOCS_BASE=7d1f1bb7ed2f097beb5376eb48f08cfeed794c3b npm run verify",
"result": "green",
"at": "65914e2fa53c26c0bc43ae3420b379c7ea8bf1c2"
},
"next": "T2: waiting for Birfy's PASS at head 65914e2; the pushed head carries the identical tree 35f280d7."
}

Two lanes from different Projects read the same inside the assign dialog:
the target row carried the name and the chain, never the Project the list row
already draws. The dialog now repeats that badge from the same projects
listing, and a lane with no Project draws none.
@Birfy

Birfy commented Nov 3, 2026

Copy link
Copy Markdown
Collaborator

Verdict: PASS at 65914e2
Written-by: Reviewer
Attestation: 65914e2 role=Reviewer

Ran at this tip:

$ cd w2242/tip && TZ=UTC node --test plugins/workflow/test/client.test.js
# tests 150  # pass 150  # fail 0
$ cd w2242 && cp base/plugins/workflow/client.js red/plugins/workflow/client.js && cd red && TZ=UTC node --test plugins/workflow/test/client.test.js
# tests 150  # pass 148  # fail 2
$ cd w2242/tip && TZ=UTC npm --prefix plugins/workflow test
# tests 391  # pass 390  # fail 1

Red first, as required: on the tip tree with only plugins/workflow/client.js swapped back to its 7d1f1bb7 blob (the tip's tests kept), the two new cases go red — not ok 148 (the pick row drew Lane AWorkflow, its Project badge absent) and not ok 149 (0 Project badges where 2 lanes have one, 0 !== 2) — while ok 150 (the assign body is unchanged) already passes on the base, which is the point of that third test. Restoring the tip file puts all 150 back to green.

Review points:

  • The change is the one the issue names: AssignModal gains projects, resolves a name once via projectName(id) over the same listing the list row already uses (client.js:2232), and draws a wf-proj span after the Workflow badge on each target row; a lane with no projectId draws no badge (owner decision in workflow: Hand a task lists lanes by name only — the dialog never says which Project the choice files into #2241), and the list row's own Unassigned branch is untouched. The assign call gains no projectId, and confirmAssign's submit body is unchanged — pinned by the third test.
  • Workflow plugin suite at this tip is 391 tests / 390 pass / 1 fail, and that one is not ok 21 - test/host.test.js: it fails identically at base 7d1f1bb7 (388/387/1), so it is the box's missing host deps, not this diff. The affected file is otherwise green.
  • Check-runs at this tip (15): the only red is enqueue-guard, whose own reason is do not enqueue #2242: no Verifier report names the tip 65914e2fa53c — the pre-verdict state, not a code failure. tests-ok, package, judge, the four plugins jobs, Node 24, merge-gate, risk tier (report only), reviewed tip are all success; no hold.
  • Scope: compare 7d1f1bb7…65914e2f is one commit on a single parent, 4 files / +88/−4 — plugins/workflow/client.js (+8/−3), plugins/workflow/test/client.test.js (+78), docs/subsystems/workflow.md (+1/−1), changelog.d/2241-hand-a-task-project-badge.added.md (+1). Exactly the declared set, nothing outside the issue.
  • Docs and changelog both name the dialog, so the Project paragraph and the fragment stay in step with the code.
  • Checkpoint block is compliant: 1082 characters with markers, summary 470, next 99, 4 files all in this diff, checks.at = this tip, ran = the npm run verify the author reports green on the identical tree 35f280d7.
  • Metadata: body carries Owner: Dev / Reviewer: Birfy (not the same name). The head lives in HugoXK/FlyBot, a fork, so agent-pr is not asked of it — same reading as social: a read-only window's read endpoints write no settings file #2236.

Not run here: the full npm run verify — this box has no dev/harness / jsdom deps, so only the affected suite and its red control were executed; tests-ok, plugins (workflow) and package are green on this very tip. The CI package job's typecheck, actionlint and pack check were likewise not run locally. Nothing else needed holding.

@github-actions github-actions Bot added the pass label Nov 3, 2026
@Birfy
Birfy added this pull request to the merge queue Nov 3, 2026
Merged via the queue into ThinkFlowLab:main with commit 6f862cd Nov 3, 2026
14 of 15 checks passed
@Birfy
Birfy deleted the dev/1-p450-assign-dialog-project branch November 3, 2026 01:18
HugoXK added a commit to HugoXK/FlyBot that referenced this pull request Nov 3, 2026
…2255)

Written-by: Dev-4
Fixes ThinkFlowLab#2254

Owner: Dev4
Reviewer: Birfy
Tier: T2
Claim-Id: 860a1014446b40ccb2e6300985f9d78e
Branch: dev/4-p463-assign-names-target
Base: 575fadf
Tree: d5e92ac
Verified commit: local `49261b05b3dc120dd722799d324dc5c515f2178e` (not
on the remote; the same tree as `Tree` above, pushed as
`c5f7e5dbe77002f45b7ff9f0e42cffb1234c5a1d`)
Pushed head: c5f7e5d
Files: 4 changed, +89/−8

## The defect

**Hand a task to a Workflow** gained two ways to tell two lanes apart —
the Project badge on every target row (`ThinkFlowLab#2242`) and the Project on the
row a lane's own name sits in (`ThinkFlowLab#2241`) — but the confirm button still
read `Assign` alone (`plugins/workflow/client.js` base :1504, tip
:1512–1513). With two lanes that share one name, the identifying row
scrolls out of the dialog's footer exactly when the person presses the
button, so the last thing read before the click cannot say which lane
the card goes to.

## Red first, on live main `575fadf3`

Clean tree at `575fadf346e4297c641f74a5d79244d1ccf0cb58` with only
`plugins/workflow/test/client.test.js` carrying the new cases (base
sources, so the button still reads `Assign`):

- `plugins/workflow/test/client.test.js` → **404 tests / 401 pass / 3
fail**
- `not ok 208 - ThinkFlowLab#2254: two lanes with one name: the confirm button names
the picked lane and its Project` — `the default lane's Project is on the
button, saw Assign` (`expected: true`, `actual: false`)
- `not ok 209 - ThinkFlowLab#2254: a Bot target names the Bot on the confirm button`
— `expected: 'Assign to Writer Bot'`, `actual: 'Assign'`
- `not ok 210 - ThinkFlowLab#2254: the named confirm button posts the same assign
body` — `precondition: the second lane is the target` (`expected: true`,
`actual: false`); its own body assertion is the regression guard for the
unchanged `workflow/assign` payload, and it is the label line that fails
on the base.
- The fixture is two lanes both named `Release lane`, one in Project
`Alpha` and one in `Beta`: the default pick must name `Alpha`, picking
the second must name `Beta` and drop `Alpha`, a Bot target must name the
Bot, and the confirm click must still post exactly one `workflow/assign`
with `{ workflowId, taskId, title }`.

The base already carries `ThinkFlowLab#2252`'s cases, so the three new failures sit
at 208/209/210.

## The fix

The footer button names the target it is about to use
(`plugins/workflow/client.js` tip :1512–1513, the label reads
`targetName`, resolved once per render at tip :1451–1454):

```js
targetName ? tr('Assign to {target}', { target: targetName }) : tr('Assign')
```

`targetName` is resolved once per render from the same state the click
posts: the Bot's name for a `bot:<id>` target, else the picked lane's
name with its Project — `Release lane · Beta` — else `''`. A dialog with
no target keeps today's plain `Assign`, still disabled (`ThinkFlowLab#2245`'s
behaviour, pinned by that case). Nothing else moves: `canAssign`,
`target`, `taskId`, the submit body and the `ThinkFlowLab#2244` expanders are
byte-identical.

- `plugins/workflow/client.js` (+10/−1): the label and its three-line
comment, plus the `Assign to {target}` entry in the plugin's own zh
fallback dictionary.
- `plugins/workflow/test/client.test.js` (+77/−6): the three new cases,
plus the six places that found the button by the exact text `Assign` now
match the same button by its unchanged prefix.
- `docs/subsystems/workflow.md` (+1/−1): one sentence stating the rule
next to the Project-badge rule it completes.
- `changelog.d/2254-hand-a-task-names-its-target.changed.md` (+1).

## Delta, file by file

| file | +/- | kind |
| --- | --- | --- |
| `plugins/workflow/client.js` | +10/−1 | written |
| `plugins/workflow/test/client.test.js` | +77/−6 | written (new cases
and the finder prefix) |
| `docs/subsystems/workflow.md` | +1/−1 | written |
| `changelog.d/2254-hand-a-task-names-its-target.changed.md` | +1 |
written (new) |
| **total** | **+89/−8** | 4 files, no generated file |

`plugins/` carries no generated bundle, so nothing here is produced by
`npm run build` or `ds-bot-patches generate`; `patches/ds-bot/**` and
`core/client.js` are untouched, and `node scripts/ds-bot-patches.mjs
generate` after the edit left `patches/` byte-identical.

## What I ran at local `49261b05b3dc120dd722799d324dc5c515f2178e`
(pushed as `c5f7e5dbe77002f45b7ff9f0e42cffb1234c5a1d`)

`TZ=UTC ARCH_DOCS_BASE=575fadf346e4297c641f74a5d79244d1ccf0cb58 npm run
verify` → **exit 0**

| suite | tests / pass / fail |
| --- | --- |
| core | 2675 / 2675 / 0 |
| plugins/social | 570 / 570 / 0 |
| plugins/tree | 132 / 132 / 0 |
| plugins/timeline | 140 / 140 / 0 |
| plugins/workflow | 404 / 404 / 0 |
| `.github/scripts` | 599 / 599 / 0 |
| interop | 37 / 37 / 0 |
| live-e2e | 26 / 26 / 0 |
| **total** | **4583 / 4583 / 0** |

- After the fix, `plugins/workflow/test/client.test.js` on its own:
**404 / 404 / 0** (the base's 401 plus the three that were red).
- `arch-docs: OK (4 changed file(s))`; oxlint **0 errors** in every
suite (74/36/9/2/16 warnings, the same counts as live main; interop 1,
live-e2e 0).
- `ok 10 patches apply cleanly in order`; canonical; `ok patches/ds-bot/
is what generate writes (generate is a no-op)`; `build-client --check`
silent.

## Tier, by path (not by a label)

`createGate(risk-rules).judge(files)` over exactly these four paths,
from `575fadf3`'s `.github/agent/risk-rules.json`:

`risk-tier: T2; basis: plugins/workflow/client.js=T2,
plugins/workflow/test/client.test.js=T2,
changelog.d/2254-hand-a-task-names-its-target.changed.md=T1,
docs/subsystems/workflow.md=T0`

97 changed lines in 4 files, no generated file.

## Not run

- The smoke bench (`dev/bench.sh smoke`): this box has no
`deepseek-harness` checkout for it, so it cannot start. `core/index.js`
and `core/src/host/` are untouched by this change.
- No browser was available, so the dialog states are exercised through
the module tests rather than by clicking.

## Checkpoint

<!-- flybot:checkpoint -->
{
  "pr": 2255,
  "claim": "Dev4",
  "issue": 2254,
"summary": "The confirm button of Hand a task to a Workflow now names
the target it will use: the picked lane with its Project, or the Bot. It
read Assign alone before, so two lanes that share one name were
indistinguishable at the click. The name comes from the same state the
click posts, and the submit body stays { workflowId, taskId, title };
with no target the plain Assign stays disabled as ThinkFlowLab#2245 left it. Three
client tests drive two lanes named alike from Projects Alpha and Beta,
and a Bot target.",
  "files": [
    "plugins/workflow/client.js",
    "plugins/workflow/test/client.test.js",
    "docs/subsystems/workflow.md",
    "changelog.d/2254-hand-a-task-names-its-target.changed.md"
  ],
  "checks": {
"ran": "TZ=UTC ARCH_DOCS_BASE=575fadf3 npm run verify (4583/4583/0)",
    "result": "green",
    "at": "c5f7e5dbe77002f45b7ff9f0e42cffb1234c5a1d"
  },
"next": "T2: waiting for a PASS naming this tip; enqueue-guard will
refuse until one exists"
}
<!-- /flybot:checkpoint -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

workflow: Hand a task lists lanes by name only — the dialog never says which Project the choice files into

2 participants